﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace SimpleSocket
{
    public class ReceivedMessageEventArgs : EventArgs
    {
        /// <summary>
        /// DateTime the message started to come into the socket
        /// </summary>
        public DateTime StartedReceivingAt { get; set; }

        /// <summary>
        /// DateTime the Socket completed receiving the message.
        /// </summary>
        public DateTime CompletedReceivingAt { get; set; }

        /// <summary>
        /// If true the other end is waiting on a responce. Use SendResponce() to respond.
        /// </summary>
        public bool ResponceRequested { get; set; }

        /// <summary>
        /// Custom Command
        /// </summary>
        public int Command { get; set; }

        /// <summary>
        /// Custom CommandText
        /// </summary>
        public string CommandText { get; set; }

        /// <summary>
        /// Data package that was received.
        /// </summary>
        public byte[] Data { get; set; }

        /// <summary>
        /// SendResponce can only be sent once.
        /// </summary>
        public bool ResponceSent { get; private set; }

        private uint ResponceID;
        private SimpleSocketClient Client;

        internal ReceivedMessageEventArgs(SimpleSocketClient client, Message msg)
        {
            Client = client;
            ResponceRequested = msg.ResponceRequested;
            ResponceID = msg.ResponceID;
            Command = msg.Command;
            CommandText = msg.CommandText;
            Data = msg.ReceivedData;
            StartedReceivingAt = msg.ReceiveStart;
            CompletedReceivingAt = msg.ReceiveComplete;
            ResponceSent = false;
        }

        /// <summary>
        /// Used to reply back to the server.
        /// </summary>
        /// <param name="obj"></param>
        public void SendResponce(object obj)
        {
            if (ResponceID == 0)
                throw new Exception("Cannot send responce. No responce was requested.");

            if (ResponceSent)
                throw new Exception("The responce has already been sent. Cannot send another responce.");

            ResponceSent = true;
            Client.SendResponce(ResponceID, obj);
        }

        /// <summary>
        /// Used to reply back to the server.
        /// </summary>
        /// <param name="responce"></param>
        public void SendResponce(byte[] responce)
        {
            if (ResponceID == 0)
                throw new Exception("Cannot send responce. No responce was requested.");

            if (ResponceSent)
                throw new Exception("The responce has already been sent. Cannot send another responce.");

            ResponceSent = true;
            Client.SendResponce(ResponceID, responce);
        }

        /// <summary>
        /// Reads the data as UTF8 string.
        /// </summary>
        /// <returns></returns>
        public string DataAsUTF8()
        {
            return Encoding.UTF8.GetString(Data);
        }

        /// <summary>
        /// Deserializes the data back into an object.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T DataAs<T>()
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream(Data);
            object value = bf.Deserialize(ms);
            ms.Dispose();
            return (T)value;
        }

    }
}
